package tools

import (
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

// FileExist 这里需要判断错误类型, 有可能是权限不足, 无法进入目录不知道目录类型
func FileExist(filePath string) (bool, error) {
	_, err := os.Stat(filePath)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) == true {
		return false, nil
	}
	return false, err
}

func IsDir(path string) (bool, error) {
	// 获取文件或目录的信息
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false, err
	}
	// 判断是否是目录
	if fileInfo.IsDir() {
		return true, nil
	} else {
		return false, nil
	}
}

func Md5(str string) string {
	h := md5.New()
	_, _ = io.WriteString(h, str)
	return fmt.Sprintf("%x", h.Sum(nil))
}

// UnixToTime 时间戳转日期
func UnixToTime(timestamp int64) string {
	t := time.Unix(timestamp, 0)
	return t.Format("2006-01-02 15:04:05")
}

// UnixToDate 时间戳转日期
func UnixToDate(timestamp int64) string {
	t := time.Unix(timestamp, 0)
	return t.Format("2006-01-02")
}

// StrToTime 时间字符串转为本地时间 => 2022-08-21 23:30:00
func StrToTime(timeStr string) int64 {
	timeTpl := "2006-01-02 15:04:05"
	t, _ := time.ParseInLocation(timeTpl, timeStr, time.Local)
	return t.Unix()
}

// GetNow 获取当前日期 年月日 时分秒
func GetNow() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

// GetDate 获取当前日期 年月日 => 20220821
func GetDate() string {
	return time.Now().Format("20060102")
}

// GetMicro 获取当前微秒级时间戳 =>
func GetMicro() string {
	micro := time.Now().UnixMicro()
	return strconv.FormatInt(micro, 10)
}

// GetNano 获取当前纳秒级时间戳 =>
func GetNano() string {
	nano := time.Now().UnixNano()
	return strconv.FormatInt(nano, 10)
}

// UrlReset 重构url参数
func UrlReset(originUrl string, parameters map[string]string) (dstUrl string, err error) {
	resUrl, err := url.Parse(originUrl)
	if err != nil {
		return
	}
	params := url.Values{}
	for key, val := range parameters {
		params.Set(key, val)
	}
	if resUrl.RawQuery == "" {
		resUrl.RawQuery = params.Encode()
	} else {
		resUrl.RawQuery = resUrl.RawQuery + "&" + params.Encode()
	}
	dstUrl = resUrl.String()
	return
}

// GetRandomString 随机字符串
func GetRandomString(n int) string {

	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	var result []byte
	for i := 0; i < n; i++ {
		result = append(result, bytes[rand.Intn(len(bytes))])
	}
	return string(result)
}

// GetRandomNumberStr 随机数字字符串
func GetRandomNumberStr(n int) string {
	rand.Seed(time.Now().UnixNano())
	str := ""
	for i := 0; i < n; i++ {
		str += strconv.Itoa(rand.Intn(10))
	}
	return str
}

// 截取字符串，支持多字节字符
// start：起始下标，负数从从尾部开始，最后一个为-1
// length：截取长度，负数表示截取到末尾

func SubStr(str string, start int, length int) (result string) {
	s := []rune(str)
	total := len(s) // 全部字数
	if total == 0 {
		return
	}
	// 允许从尾部开始计算
	if start < 0 {
		start = total + start
		if start < 0 {
			return
		}
	}
	if start > total {
		return
	}
	// 到末尾
	end := total
	if length == 0 {
		end = total
	} else if length < 0 {
		end = total + length
	} else {
		end = start + length
	}
	if end <= start {
		return
	}
	if end > total {
		result = string(s[start:])
	} else {
		result = string(s[start:end])
	}
	return
}

// 分隔符拼接数组

func JoinIntArray(arr []int, separator string) string {
	if len(arr) > 0 {
		str := ""
		for _, v := range arr {
			str += fmt.Sprintf("%v%v", v, separator)
		}
		return SubStr(str, 0, -1)
	}
	return ""
}

func JoinStringArray(arr []string, separator string) string {
	if len(arr) > 0 {
		str := ""
		for _, v := range arr {
			str += fmt.Sprintf("%v,", v)
		}
		return SubStr(str, 0, -1)
	}
	return ""
}

type IpLocation struct {
	Status    string `json:"status"`
	Info      string `json:"info"`
	InfoCode  string `json:"infocode"`
	Province  string `json:"province"`
	City      string `json:"city"`
	AdCode    string `json:"adcode"`
	Rectangle string `json:"rectangle"`
}

func GetLocationByIP(ip string) (location *IpLocation, err error) {
	key := "3a69bef99855dc5d7e80809e59111a4b"
	params := url.Values{}
	params.Set("key", key)
	params.Set("ip", ip)
	reqUrl := "https://restapi.amap.com/v3/ip?" + params.Encode()
	fmt.Println("高德地图:  ", reqUrl)
	response, err := http.Get(reqUrl) //发起get请求
	if err != nil {
		return
	}
	defer response.Body.Close()                //关闭请求
	body, err := ioutil.ReadAll(response.Body) //解析请求信息
	if err != nil {
		return
	}
	location = &IpLocation{}
	err = json.Unmarshal(body, location) //转换为map
	if err != nil {
		return
	}
	if location.Status == "0" {
		err = errors.New(location.Info)
		return
	}
	return
}

// ReadFileContent 读取文件内容
func ReadFileContent(filePath string) (contentStr string, err error) {
	contentByte, err := os.ReadFile(filePath)
	if err != nil {
		return
	}
	contentStr = string(contentByte)
	return
}

// GetRandAreaNumber 在范围内取随机数
func GetRandAreaNumber(min int, max int) int {
	return rand.Intn(max-min+1) + min
}

func SignFromMapString(params interface{}, appSecret string) (string, error) {
	byteData, _ := json.Marshal(params)
	var data map[string]string
	err := json.Unmarshal(byteData, &data)
	if err != nil {
		//fmt.Println("JSON 解析错误:", err)
		return "", err
	}
	v := url.Values{}
	for key, value := range data {
		v.Set(key, value)
	}
	queryString := v.Encode()
	queryString = strings.ToLower(queryString + "&app_secret=" + appSecret)
	sign := Md5(queryString)
	//fmt.Println("queryString: ", queryString)
	//fmt.Println("签名: ", sign)
	return sign, nil

}
